package com.mengxin.secondkill.filter;

/**
 * @author mengxin
 * @date 2020/12/12 16:43
 */
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@WebFilter(urlPatterns = {"/*"}, filterName = "logRecordFilter")
public class LogRecordFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        JSONObject logRecord = new JSONObject(true);
        long start = System.currentTimeMillis();
        try {
            HttpServletRequest httprequest = (HttpServletRequest) request;
            HttpServletResponse Httpresponse = (HttpServletResponse) response;
            ContentCachingRequestWrapper cachingRequest = new ContentCachingRequestWrapper(httprequest);
            ContentCachingResponseWrapper cachingResponse = new ContentCachingResponseWrapper(Httpresponse);
            chain.doFilter(cachingRequest, cachingResponse);
            logRecord.put("ReqRemoteAddr", httprequest.getRemoteAddr());
            logRecord.put("ReqTime",
                    JSONObject.parse(JSON.toJSONStringWithDateFormat(new Date(), "yyyy-MM-dd HH:mm:ss.SSS")));
            logRecord.put("ReqMethod", httprequest.getMethod());
            logRecord.put("ReqURL", httprequest.getRequestURL());
            logRecord.put("ReqQueryString", httprequest.getQueryString());
            try {
                logRecord.put("ReqParam", JSONObject.parse(cachingRequest.getContentAsByteArray()));
            } catch (JSONException e) {
                logRecord.put("ReqParam", new String(cachingRequest.getContentAsByteArray()));
            }
            logRecord.put("RespStatus", cachingResponse.getStatus());
            logRecord.put("RespContentsize", cachingResponse.getContentSize());
            if (cachingResponse.getContentSize() > 1000) {
                logRecord.put("RespContent", new String(cachingResponse.getContentAsByteArray(), 0, 999));
            } else {
                logRecord.put("RespContent", JSONObject.parse(cachingResponse.getContentAsByteArray()));
            }
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
                    .getRequestAttributes();
            Throwable exception = (Throwable) requestAttributes
                    .getAttribute(String.format("%s.ERROR", DefaultErrorAttributes.class.getName()), RequestAttributes.SCOPE_REQUEST);
            if (null != exception) {
                logRecord.put("RespContentsize", null!=exception.getMessage()?exception.getMessage().getBytes().length:0);
                logRecord.put("RespContent", exception.getMessage());

            }
            logRecord.put("TimeCost", String.format("%sms", System.currentTimeMillis() - start));
            log.info(logRecord.toString());
            cachingResponse.copyBodyToResponse();
        } catch (Exception e) {
            log.error("filter exception,request content:{}", logRecord.toString(), e);
        }

    }

    @Override
    public void destroy() {

    }

}

